package com.lzh.runke.core.web_base.enums.deserializer;

import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonNode;
import com.lzh.runke.core.web_base.enums.BaseEnum;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;

import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @Description: 枚举反序列化器
 * @Author: LiuZiHao
 * @Date: 2022/4/27 17:09
 */
@SuppressWarnings("unchecked")
public class EnumDeserializer extends JsonDeserializer<BaseEnum> {

    @Override
    @SuppressWarnings("unchecked")
    public BaseEnum deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {

        JsonNode node = jp.getCodec().readTree(jp);

        //枚举处理.value 形式
        if (StringUtils.isBlank(node.get("value").asText())) {
            return null;
        }

        //实体类
        Object currentValue = jp.getCurrentValue();

        if (null == currentValue) {

        }

        // 实体类中枚举属性名
        String currentName = jp.currentName();

        Class clazz = BeanUtils.findPropertyType(currentName, currentValue.getClass());
        JsonFormat annotation = (JsonFormat) clazz.getAnnotation(JsonFormat.class);
        //枚举
        BaseEnum em;
        if (annotation == null || annotation.shape() != JsonFormat.Shape.OBJECT) {
            em = (BaseEnum) Enum.valueOf(clazz, node.get("value").asText());
        } else {
            List<BaseEnum> enums = Arrays.asList((BaseEnum[]) clazz.getEnumConstants());
            //枚举处理.value 形式
            List<BaseEnum> matched = enums.parallelStream().filter(e -> node.get("value").asText().equals(e.getValue().toString())).collect(Collectors.toList());

            if (matched.stream().findFirst().isPresent()) {
                em = matched.stream().findFirst().get();
            } else {
                throw new RuntimeException(node.asText() + "未匹配上对应的枚举");
            }
        }
        return em;
    }
}
